/*
 * @Author: Du Weixing duweixing@sgsimulation.com
 * @Date: 2024-11-08 17:16:34
 * @LastEditors: Du Weixing duweixing@sgsimulation.com
 * @LastEditTime: 2024-11-08 18:07:39
 * @FilePath: \SGFEM\DataStructure\Math\test\MathToolsTest.hpp
 * @Description:
 *
 * Copyright (c) 2024 by 神工仿真, All Rights Reserved.
 */

#include "gtest/gtest.h"

//#include "../include/MathTools.h"
#include "MathTools.h"

// using SG::Algebra::Matrixd;
// using SG::Algebra::Point;
// using SG::Algebra::

using namespace SG::Algebra;

TEST (MathToolsTest, computeLocalCoordTrans)
{
    // Input data
    Vector3D xVec{ 1.0, 0.0, 0.0 };
    Vector3D orien{ 0.0, 1.0, 0.0 };

    // Test data
    Matrixd TTest (3, 3);
    computeLocalCoordTrans (xVec, orien, _OUT TTest);

    // Target data
    auto TTarget = identity (3);

    // Check
    ASSERT_TRUE (TTarget == TTest);
}

TEST (MathToolsTest, computeLocalCoordTransWithTwoPoint)
{
    // Input data
    const Point point1{0.0, 0.0, 0.0};
    const Point point2{2.0, 0.0, 0.0};

    // Test data
    Matrixd TTest (3, 3);
    computeLocalCoordTrans (point1, point2, _OUT TTest);

    // Target data
    const auto& TTarget = SG::Algebra::identity (3);

    // Check
    ASSERT_TRUE (TTarget == TTest);
}

TEST (MathToolsTest, computeLocalCoordTransWithTwoPoint2)
{
    // Input data
    const Point point1{0.0, 0.0, 0.0};
    const Point point2{0.49990281177625512, -6.8059896235683101e-08, -0.86608150816085971};

    // Test data
    Matrixd TTest (3, 3);
    computeLocalCoordTrans (point1, point2, _OUT TTest);

    // Target data
    const Matrixd TTarget (3, 3, {0.49990281177625512, -6.8059896235683101e-08, -0.86608150816085971,
                                  0.0,                                     1.0,                  0.0,
                                  0.86608150816085971,                     0.0,  0.49990281177625512});

    // Check
    ASSERT_TRUE (TTarget == TTest);
}

// 判断四节点单元投影点是否正确。
TEST (MathToolsTest, ProjectionPoint2Quad)
{
    // Input data
    SG::Algebra::PointArray points(4);
    points[0] = Point{1.0, 1.0, 0.0};
    points[1] = Point{2.0, 1.0, 0.0};
    points[2] = Point{2.0, 2.0, 0.0};
    points[3] = Point{1.0, 2.0, 0.0};

    Point pointcentral = { (points[2].m_x + points[0].m_x) / 2.0, (points[2].m_y + points[0].m_y) / 2.0, (points[2].m_z + points[0].m_z) / 2.0 };
    Vector3D n{0, 0, 1};

    Point gS{1.5, 1.5, 0.25};

    
    // Test data
    Point Gi;
    projectPoint2Face (pointcentral, n, gS, _OUT Gi);

    // Check
    ASSERT_NEAR (Gi.m_x, 1.5, TOLERANCE);
    ASSERT_NEAR (Gi.m_y, 1.5, TOLERANCE);
    ASSERT_NEAR (Gi.m_z, 0.0, TOLERANCE);
}

TEST (MathToolsTest, ProjectionPoint2Quad2)
{
    // 判断斜四节点单元投影点是否正确。
    // Input data
    Point Gi;
    SG::Algebra::PointArray points(4);
    points[0] = Point{0.0, 0.0, 10.0};
    points[1] = Point{100.0, 0.0, 10.0};
    points[2] = Point{100.0, 100.0, 20.0};
    points[3] = Point{0.0, 100.0, 20.0};
    auto norm = sqrt(10.0*10.0 + 1.0*1.0);
    Vector3D n{0, -1.0/norm, 10.0/norm};
    Point pointcentral = { (points[2].m_x + points[0].m_x) / 2.0, (points[2].m_y + points[0].m_y) / 2.0, (points[2].m_z + points[0].m_z) / 2.0 };
    
    Point gS{40, 10, 5};
    
    // Test data
    projectPoint2Face (pointcentral, n, gS, _OUT Gi);

    // Check
    ASSERT_NEAR (Gi.m_x, 40, TOLERANCE);
    ASSERT_NEAR (Gi.m_y, 9.405941, TOLERANCE);
    ASSERT_NEAR (Gi.m_z, 10.940594, TOLERANCE);
}

TEST (MathToolsTest, ProjectionPoint2Triface)
{
    // 判断三节点单元投影点是否正确。
    // Input data
    SG::Algebra::PointArray points(3);
    points[0] = Point{1.0, 1.0, 0.0};
    points[1] = Point{2.0, 1.0, 0.0};
    points[2] = Point{2.0, 2.0, 0.0};
    
    Vector3D n{0, 0, 1};
    Point pointcentral = { (points[2].m_x + points[0].m_x) / 2.0, (points[2].m_y + points[0].m_y) / 2.0, (points[2].m_z + points[0].m_z) / 2.0 };
    
    Point gS{1.5, 1.75, 0.25};
    
    // Test data
    Point Gi;
    projectPoint2Face (pointcentral, n, gS,_OUT Gi);

    // Check
    ASSERT_NEAR (Gi.m_x, 1.5, TOLERANCE);
    ASSERT_NEAR (Gi.m_y, 1.75, TOLERANCE);
    ASSERT_NEAR (Gi.m_z, 0.0, TOLERANCE);
}